package com.markby.fscm.cryptogram.domain.standard0016;

import lombok.Data;

import java.nio.ByteOrder;

import static com.markby.fscm.cryptogram.uitls.HexUtils.intToBytes;


/**
 * 0016-2023规范 ECC密钥对保护数据结构
 * ULONG 为32位无符号整数
 * typedefstruct Struct ENVELOPEDKEYBLOB{
 * ULONG 	Version; 					// 版本号,本版本为2
 * ULONG 	ulSymmAlgID;				// 对称算法标识(应为ECB模式)
 * ULONG 	ulBits;						// 加密密钥对的密钥位长 256或215
 * BYTE 	cbEncryptedPriKey[64];		// 对称算法加密的加密私钥,加密私钥的原文为ECCPRIVATEKEYBLOB结构中的PrivateKey(其有效长度为原文的(ulBils+7)/8)
 * ECCPUBLICKEYBLOB 	PubKey;			// 加密密钥对的公钥
 * ECCCIPHERBLOB 	ECCCipherBlob;		// 用保护公钥加密过的对称密钥密文
 * }ENVELOPEDKEYBLOB，*PENVELOPEDKEYBLOB:
 * 私钥密文数组中的有效密文分组应从0偏移量字节开始。顺序解密密文分组后将明文连接应得到加密密钥对的私钥的明文。
 */
@Data
public class ENVELOPEDKEYBLOB {
    private int Version;
    private int ulSymmAlgID;
    private int ulBits;
    private byte[] cbEncryptedPriKey;
    private ECCPUBLICKEYBLOB PubKey;
    private ECCCIPHERBLOB ECCCipherBlob;

    public ENVELOPEDKEYBLOB(int ulSymmAlgID, int ulBits, byte[] cbEncryptedPriKey, ECCPUBLICKEYBLOB PubKey, ECCCIPHERBLOB ECCCipherBlob) {
        this(2, ulSymmAlgID, ulBits, cbEncryptedPriKey, PubKey, ECCCipherBlob);
    }

    public ENVELOPEDKEYBLOB(int version, int ulSymmAlgID, int ulBits, byte[] cbEncryptedPriKey, ECCPUBLICKEYBLOB PubKey, ECCCIPHERBLOB ECCCipherBlob) {
        if (cbEncryptedPriKey.length != 64) {
            throw new IllegalArgumentException("Invalid cbEncryptedPriKey length: " + cbEncryptedPriKey.length);
        }
        this.Version = version;
        this.ulSymmAlgID = ulSymmAlgID;
        this.ulBits = ulBits;
        this.cbEncryptedPriKey = cbEncryptedPriKey;
        this.PubKey = PubKey;
        this.ECCCipherBlob = ECCCipherBlob;
    }

    public byte[] getBytes() {
        byte[] versionBytes = intToBytes(Version, ByteOrder.LITTLE_ENDIAN);
        byte[] ulSymmAlgIDBytes = intToBytes(ulSymmAlgID, ByteOrder.LITTLE_ENDIAN);
        byte[] ulBitsBytes = intToBytes(ulBits, ByteOrder.LITTLE_ENDIAN);
        byte[] cbEncryptedPriKeyBytes = cbEncryptedPriKey;
        byte[] PubKeyBytes = PubKey.getBytes();
        byte[] ECCCipherBlobBytes = ECCCipherBlob.getBytes();
        byte[] result = new byte[versionBytes.length + ulSymmAlgIDBytes.length + ulBitsBytes.length + cbEncryptedPriKeyBytes.length + PubKeyBytes.length + ECCCipherBlobBytes.length];
        System.arraycopy(versionBytes, 0, result, 0, versionBytes.length);
        System.arraycopy(ulSymmAlgIDBytes, 0, result, versionBytes.length, ulSymmAlgIDBytes.length);
        System.arraycopy(ulBitsBytes, 0, result, versionBytes.length + ulSymmAlgIDBytes.length, ulBitsBytes.length);
        System.arraycopy(cbEncryptedPriKeyBytes, 0, result, versionBytes.length + ulSymmAlgIDBytes.length + ulBitsBytes.length, cbEncryptedPriKeyBytes.length);
        System.arraycopy(PubKeyBytes, 0, result, versionBytes.length + ulSymmAlgIDBytes.length + ulBitsBytes.length + cbEncryptedPriKeyBytes.length, PubKeyBytes.length);
        System.arraycopy(ECCCipherBlobBytes, 0, result, versionBytes.length + ulSymmAlgIDBytes.length + ulBitsBytes.length + cbEncryptedPriKeyBytes.length + PubKeyBytes.length, ECCCipherBlobBytes.length);
        return result;
    }
}
